package com.pai4j.message.interceptor;

import com.pai4j.common.util.RedisUtil;
import com.pai4j.message.core.interceptor.MessageInterceptor;
import com.pai4j.message.model.MessageContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

/**
 * 限流拦截器
 * 限制用户在指定时间窗口内的消息发送频率
 * 
 * 使用Redis滑动窗口实现限流
 *
 * @author PAI4J Team
 * @date 2025-11-01
 */
@Slf4j
@Component
@ConditionalOnProperty(prefix = "pai4j.message.interceptors.rate-limit", name = "enabled", havingValue = "true", matchIfMissing = false)
public class RateLimitInterceptor implements MessageInterceptor {

    @Autowired(required = false)
    private RedisUtil redisUtil;

    /**
     * 时间窗口（秒）
     */
    private static final long TIME_WINDOW = 60L;

    /**
     * 最大消息数（每分钟）
     */
    private static final long MAX_MESSAGES = 10L;

    /**
     * 缓存Key前缀
     */
    private static final String CACHE_KEY_PREFIX = "message:ratelimit:";

    @Override
    public String getName() {
        return "rate-limit";
    }

    @Override
    public boolean intercept(MessageContext context) {
        if (redisUtil == null) {
            log.debug("RedisUtil未注入，跳过限流检查");
            return true;
        }

        try {
            String userId = context.getSenderId();
            String cacheKey = CACHE_KEY_PREFIX + userId;

            // 获取当前计数
            String countStr = redisUtil.get(cacheKey);
            long count = countStr != null ? Long.parseLong(countStr) : 0;

            // 检查是否超限
            if (count >= MAX_MESSAGES) {
                log.warn("用户消息发送超限，拦截发送: userId={}, count={}, limit={}", 
                        userId, count, MAX_MESSAGES);
                return false;
            }

            // 计数+1
            if (count == 0) {
                // 第一次，设置初始值和过期时间
                redisUtil.set(cacheKey, "1", TIME_WINDOW);
            } else {
                // 递增
                redisUtil.increx(cacheKey, TIME_WINDOW);
            }

            log.debug("限流检查通过: userId={}, count={}/{}", userId, count + 1, MAX_MESSAGES);
            return true;

        } catch (Exception e) {
            log.error("限流检查异常，允许通过: error={}", e.getMessage(), e);
            return true; // 异常时允许通过
        }
    }

    @Override
    public int getOrder() {
        return 30; // 第三优先级
    }

    @Override
    public boolean matches(MessageContext context) {
        // 只对用户消息限流，系统消息不限流
        return context != null && 
               context.getSenderId() != null && 
               !"SYSTEM".equals(context.getSenderId());
    }

    @Override
    public String getDescription() {
        return String.format("限流拦截器 - 限制用户每%d秒最多发送%d条消息", TIME_WINDOW, MAX_MESSAGES);
    }
}

